﻿#if UNITY_2019_4_OR_NEWER
#define UNITY_3D
#endif

using System.Text;

namespace Devil
{
    public delegate bool FilterDelegate<T>(T target);

    public delegate T PassDelegate<T>(T target);

    public delegate T ValueDelegate<T>();

    public delegate V GetterDelegate<in T, out V>(T target);

    public delegate void SetterDelegate<T, V>(T target, V value);

    public delegate int IdentifierDelegate<T>(T target);

    public delegate bool EquatableDelegate<T>(T a, T b);

    public static partial class ParallelUtils
    {
        static long _idPtr;
        static readonly object _lock = new object();
        static ObjectPool<StringBuilder> mBuilders = new ObjectPool<StringBuilder>(32, () => new StringBuilder(128));

        public static StringBuilder GetBuilder()
        {
            StringBuilder builder = mBuilders.Get();
            //builder.Remove(0, builder.Length);
            builder.Clear();
            return builder;
        }

        public static StringBuilder GetBuilder(string data)
        {
            StringBuilder builder = mBuilders.Get();
            //builder.Remove(0, builder.Length);
            builder.Clear();
            if (!string.IsNullOrEmpty(data))
                builder.Append(data);
            return builder;
        }

        public static string ReturnRelease(StringBuilder builder)
        {
            string ret = builder.ToString();
            mBuilders.Add(builder);
            return ret;
        }

        public static void Release(StringBuilder builder)
        {
            mBuilders.Add(builder);
        }

        public static StringBuilder AppendTab(this StringBuilder buffer, int tabs)
        {
            for (int i = 0; i < tabs; i++)
                buffer.Append('\t');
            return buffer;
        }

        public static StringBuilder NextLine(this StringBuilder buffer)
        {
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
            buffer.Append("\r\n");
#else
            buffer.Append('\n');
#endif
            return buffer;
        }

        public static string GetDelegateName(this System.Delegate dele)
        {
            var buf = GetBuilder();
            buf.Append(dele.Method.DeclaringType.FullName);
            buf.Append('.');
            buf.Append(dele.Method.Name);
            return ReturnRelease(buf);
        }

        public static string Concat(object a, object b)
        {
            var buf = GetBuilder();
            buf.Append(a).Append(b);
            return ReturnRelease(buf);
        }

        public static string Concat(object a, object b, object c)
        {
            var buf = GetBuilder();
            buf.Append(a).Append(b).Append(c);
            return ReturnRelease(buf);
        }

        public static string Concat(object a, object b, object c, object d)
        {
            var buf = GetBuilder();
            buf.Append(a).Append(b).Append(c).Append(d);
            return ReturnRelease(buf);
        }

        public static string Concat(object a, object b, object c, object d, object e)
        {
            var buf = GetBuilder();
            buf.Append(a).Append(b).Append(c).Append(d).Append(e);
            return ReturnRelease(buf);
        }

        public static string Concat(object a, object b, object c, object d, object e, object f)
        {
            var buf = GetBuilder();
            buf.Append(a).Append(b).Append(c).Append(d).Append(e).Append(f);
            return ReturnRelease(buf);
        }

        public static string Concat(object a, object b, object c, object d, object e, object f, object g)
        {
            var buf = GetBuilder();
            buf.Append(a).Append(b).Append(c).Append(d).Append(e).Append(f).Append(g);
            return ReturnRelease(buf);
        }

        public static string Concat(object a, object b, object c, object d, object e, object f, object g, params object[] others)
        {
            var buf = GetBuilder();
            buf.Append(a).Append(b).Append(c).Append(d).Append(e).Append(f).Append(g);
            for (int i = 0; i < others.Length; i++)
            {
                buf.Append(others[i]);
            }
            return ReturnRelease(buf);
        }

        public static int Max(int a, int b)
        {
            return a < b ? b : a;
        }

        public static int Min(int a, int b)
        {
            return a < b ? a : b;
        }

        public static void EnsureNativeSize<T>(ref T[] arr, int dataCount, int newSize, float resizeRatio = 1.5f)
        {
            if (newSize > 0 && arr == null || arr.Length < newSize)
            {
                var size = Max(arr == null ? (newSize + 4) : (int)System.Math.Ceiling(arr.Length * resizeRatio), newSize);
                var cp = new T[size];
                if (dataCount > 0)
                    System.Array.Copy(arr, cp, dataCount);
                arr = cp;
            }
        }
        public static int GenUniqueID()
        {
            var v = System.DateTime.UtcNow.Ticks;
            lock (_lock)
            {
                return unchecked((int)((v << 5) - v + ++_idPtr));
            }
        }
    }

}
